package org.dsbackend.controller;

import org.dsbackend.entity.JsonData;
import org.dsbackend.entity.ResultException;
import org.dsbackend.model.Authority;
import org.dsbackend.model.User;
import org.dsbackend.repository.AuthorityRepository;
import org.dsbackend.repository.UserRepository;
import org.dsbackend.util.CharUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.NoSuchElementException;

@RestController
@RequestMapping(value="/users")
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private AuthorityRepository authorityRepository;

    @RequestMapping(value="/", method=RequestMethod.GET)
    public JsonData getUserList() {
        return null;
    }

    @PreAuthorize("hasRole('SYSTEM_MANAGER')")
    @RequestMapping(value="/", method=RequestMethod.POST)
    public JsonData postUser(@RequestParam(value = "username") String username,
                             @RequestParam(value = "password") String password,
                             @RequestParam(value = "realName") String realName,
                             @RequestParam(value = "email") String email) {
        if(CharUtils.hasIllegalChar(username,password,realName))
            throw new ResultException(401,"Illegal parameters");
        if(!CharUtils.checkEmail(email))
            throw new ResultException(401,"Illegal email");
        User user =new User();
        BCryptPasswordEncoder encode = new BCryptPasswordEncoder();
        user.setUsername(username);
        user.setPassword(encode.encode(password));
        user.setRealName(realName);
        user.setEmail(email);
        List<Authority>authorities =new ArrayList<>();
        authorities.add(authorityRepository.findAllByName("ROLE_CUSTOMER"));
        user.setAuthorities(authorities);
        user.setAddresses(null);
        user.setEnabled(true);
        user.setLastPasswordResetDate(new Date());
        try{
            userRepository.save(user);
        }
        catch (DataIntegrityViolationException e)
        {
            throw new ResultException(403,"Duplicate username");
        }
        catch (Exception e)
        {
            throw new ResultException(402,e.toString());
        }
        return new JsonData(0,"success",null);
    }

    @PreAuthorize("hasRole('SYSTEM_MANAGER')")
    @RequestMapping(value="/{id}", method=RequestMethod.GET)
    public JsonData getUser(@PathVariable Long id) {
        User user=null;
        try{
            user=userRepository.findById(id).get();
        }
        catch (NoSuchElementException e)
        {
            throw new ResultException(401,"No user found");
        }
        return new JsonData(0,"success",user);
    }

    @PreAuthorize("hasRole('SYSTEM_MANAGER')")
    @RequestMapping(value="/{id}", method=RequestMethod.POST)
    public JsonData putUser(@PathVariable Long id,
                            @RequestParam(value = "username",required = false) String username,
                            @RequestParam(value = "password",required = false) String password,
                            @RequestParam(value = "realName",required = false) String realName,
                            @RequestParam(value = "email",required = false) String email) {
        User user=null;
        try{
            user=userRepository.findById(id).get();
        }
        catch (NoSuchElementException e)
        {
            throw new ResultException(401,"No user found");
        }
        if(username!=null&&!username.equals("")&&!CharUtils.hasIllegalChar(username))
            user.setUsername(username);
        if(password!=null&&!password.equals("")&&!CharUtils.hasIllegalChar(password))
            user.setPassword(password);
        if(realName!=null&&!realName.equals("")&&!CharUtils.hasIllegalChar(realName))
            user.setRealName(realName);
        if(email!=null&&!email.equals("")&&CharUtils.checkEmail(email))
            user.setEmail(email);
        try{
            userRepository.save(user);
        }
        catch (DataIntegrityViolationException e)
        {
            throw new ResultException(403,"Duplicate username");
        }
        catch (Exception e)
        {
            throw new ResultException(402,e.toString());
        }
        return new JsonData(0,"success",null);
    }

    @RequestMapping(value="/{id}", method=RequestMethod.DELETE)
    public JsonData deleteUser(@PathVariable Long id) {
        User user=null;
        try{
            user=userRepository.findById(id).get();
        }
        catch (NoSuchElementException e)
        {
            throw new ResultException(401,"No user found");
        }
        user.setEnabled(false);
        try{
            userRepository.save(user);
        }
        catch (Exception e)
        {
            throw new ResultException(402,e.toString());
        }
        return new JsonData(0,"success",null);
    }
}
